package edu.sjtu.grid.workflow.group;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import edu.sjtu.grid.workflow.facts.Facts;
import edu.sjtu.grid.workflow.facts.Job;
import edu.sjtu.grid.workflow.graph.Graph;
import edu.sjtu.grid.workflow.graph.Node;
import edu.sjtu.grid.workflow.iterator.UpwardRankIterator;

public class GroupGraph implements Graph{
	
	private double deadline = 0;
	private double unit = 0;
	
	private Facts facts = null;
	
	Map<Job, GroupNode> jobToGroupNode = null;
	GroupNode groupNodeList[] = null;
	
	public GroupGraph(Facts facts)
	{
		this.facts = facts;
		
		//init
		ArrayList<ArrayList<Job>> groupList = new ArrayList<ArrayList<Job>>();
		initGroupList(groupList);
		
		//new GroupNode
		this.jobToGroupNode = new HashMap<Job, GroupNode>();
		this.groupNodeList = new GroupNode[groupList.size()];
		for(int i=0; i<groupList.size(); i++)
		{
			ArrayList<Job> al = groupList.get(i);
			GroupNode gn = new GroupNode(this.facts, al);
			for(Job job : al)
				this.jobToGroupNode.put(job, gn);
			this.groupNodeList[i] = gn;
		}
		
		//add parent child
		for(Job parentJob : this.facts.getAdag().getJobList())
		{
			for(Job childJob : parentJob.getChildJobList())
			{
				GroupNode parentNode = jobToGroupNode.get(parentJob);
				GroupNode childNode = jobToGroupNode.get(childJob);
				parentNode.addChild(childNode);
				childNode.addParent(parentNode);
			}
		}
	}

	private ArrayList<ArrayList<Job>> initGroupList(ArrayList<ArrayList<Job>> list)
	{
		Map<Job, ArrayList<Job>> map = new HashMap<Job, ArrayList<Job>>();
		for(Job job : this.facts.getAdag().getEntryJobList())
			initGroupListHelper(job, list, map);
		return list;
	
	}
	private void initGroupListHelper(Job job, ArrayList<ArrayList<Job>> list, Map<Job, ArrayList<Job>> map)
	{
		if(map.containsKey(job))
			return;
		
		ArrayList<Job> al = null;
		if(job.getParentNumber() == 1 && job.getParentJobList().get(0).getChildNumber() == 1)
		{
			al = map.get(job.getParentJobList().get(0));
			al.add(job);
			map.put(job, al);
		}
		else
		{
			al = new ArrayList<Job>();
			list.add(al);
			al.add(job);
			map.put(job, al);
		}
		

		for(Job c : job.getChildJobList())
			initGroupListHelper(c, list, map);
	}

	public String toString()
	{
		StringBuilder s = new StringBuilder();
		
		s.append("----------GroupGraph----------\n");
		s.append("type\t\tupward rank\tLFT\n");
		for(GroupNode gn : this.groupNodeList)
			s.append(gn.toString());
		
		return s.toString();
	}
	
	@Override
	public Node[] getNodeList() {
		return this.groupNodeList;
	}

	@Override
	public UpwardRankIterator getUpwardRankIterator()
	{
		return new UpwardRankIterator(this);
	}
	
	public double getDeadline()
	{
		return this.deadline;
	}
	
	public double getUnit()
	{
		return this.unit;
	}
	
	public void setDeadline(double deadline)
	{
		this.deadline = deadline;
	}
	
	public void setUnit(double unit)
	{
		this.unit = unit;
	}
}
